#include <iostream>
#include <string>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

class Server {
public:
    /**
     * 创建一个新的socket
     * @param port 要监听的端口号
     * @return 成功返回0，失败返回-1
     */
    int createSocket(int port) {
        // 创建一个新的socket
        server_fd = socket(AF_INET, SOCK_STREAM, 0);
        if (server_fd == -1) {
            std::cerr << "Error creating socket\n";
            return -1;
        }

        // 设置ip和端口号
        address.sin_family = AF_INET;
        address.sin_addr.s_addr = INADDR_ANY;
        address.sin_port = htons(port);

        // 将socket绑定到指定ip和端口上
        if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
            std::cerr << "Bind failed\n";
            return -1;
        }

        // 等待连接，最多可以容纳3个客户端
        if (listen(server_fd, 3) < 0) {
            std::cerr << "Listen failed\n";
            return -1;
        }

        return 0;
    }

    /**
     * 接受一个新的客户端连接
     * @return 成功返回0，失败返回-1
     */
    int acceptConnection() {
        int addrlen = sizeof(address);
        new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
        if (new_socket < 0) {
            std::cerr << "Accept failed" << std::endl;
            return -1;
        }

        return 0;
    }


    std::string receiveData() {
        char buffer[1024] = {0};
        int valread = read(new_socket, buffer, 1024);
        return std::string(buffer);
    }

    void sendData(const std::string& data) {
        send(new_socket, data.c_str(), data.length(), 0);
    }

private:
    int server_fd;
    int new_socket;
    struct sockaddr_in address;
};

int main() {
    Server server;
    if (server.createSocket(8089) != 0) {
        return 1;
    }

    if (server.acceptConnection() != 0) {
        return 1;
    }

    std::string receivedData = server.receiveData();
    std::cout << "Received: " << receivedData << std::endl;

    server.sendData("Hello from server");
    std::cout << "Response sent" << std::endl;

    return 0;
}